<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
 * Authentication Model
 * 
 * @package     Authentican
 * @category    Library
 * @author      Gene Bryan Ronquillo
 * @link        http://generonquillo.com
 * @version     1.0
 */

class Auth_model extends CI_Model {
    
    public $user_tbl 		= 'users';
	public $perm_tbl 		= 'permissions';
	public $role_tbl 		= 'roles';
	public $roleperm_tbl 	= 'role_permissions';
	public $rolemenu_tbl	= 'role_menus';
	public $userweb_tbl 	= 'user_websites';
    
    // ------------------------------------------------------------------------
    
    /**
     * Construct
     * 
     */
    public function __construct()
    {
        parent::__construct();
    }
    
    // ------------------------------------------------------------------------
    
    /**
     * Hashes a string with salt
     *
     */
    public function _hash_string($str = '', $salt = '')
    {
        if (! $str) return FALSE;
        
        return sha1(md5($str) . $salt);
    }
    
    // ------------------------------------------------------------------------
    
    /**
     * Create random salt value
     * 
     */
    public function _salt($len = 16)
    {
        $this->load->helper('string');
        return random_string('alnum', $len);
    }
    
    // ------------------------------------------------------------------------
    
	/**
	 * Register or Create User
	 *
	 */
    public function register($fields = '', $others = '')
    {
        $salt       = $this->_salt();
        $password   = $this->_hash_string($fields['password'], $salt);
        $date       = date('Y-m-d H:i:s');
        
        $data = array(
            // 'username'      => $fields['username'],
            'password'      => $password,
            'email'         => $fields['email'],
            'salt'          => $salt,
            'created'       => $date
        );
        
        $user_data = array_merge($others, $data);
        $this->db->insert($this->user_tbl, $user_data);
        
        return $this->db->affected_rows() > 0 ? $this->get_user($this->db->insert_id()) : FALSE;
    }
    
    // ------------------------------------------------------------------------
    
	/**
	 * Get User
	 *
	 * @param	string	value
	 * @param	string	field
	 * @param	string	select parameters
	 */
    public function get_user($value = '', $field = 'u.user_id', $params = '*')
    {
        if (($field == 'u.user_id') && ($value == ''))
        {
            // get logged in user_id
            $value = $this->session->userdata('user_id');
			
			// no session user id
			if (! $value) return FALSE;
        }
        
        $query = $this->db->select($params)
						  ->join($this->role_tbl . ' AS r', 'r.role_id = u.role_id', 'left')
						  // ->join($this->userweb_tbl . ' AS uw', 'uw.user_id = u.user_id', 'left')
                          ->where($field, $value)
                          ->where('u.deleted', 'n')
                          ->get($this->user_tbl . ' AS u', 1);
                          
        return $query->num_rows() > 0 ? $query->row_array() : FALSE;
    }
    
    // ------------------------------------------------------------------------
    
	/**
	 * Login User
	 *
	 * Get the user's salt and hash it with the given password
	 *
	 */
    public function login($fields)
    {
        $user       = $this->get_user($fields['email'], 'email', 'salt');
        $password   = $this->_hash_string($fields['password'], $user['salt']);
        
        $query = $this->db->where('email', $fields['email'])
                          ->where('password', $password)
                          ->where('deleted', 'n')
                          ->get($this->user_tbl, 1);
        
        return $query->num_rows() > 0 ? $query->row_array() : FALSE;
    }
    
    // ------------------------------------------------------------------------
    
	/**
	 * Update Last Activity
	 *
	 * @access	private
	 * @param	int
	 * @return	bool
	 */
    public function update_last_activity($user_id = '')
    {
        $data['last_activity'] = date('Y-m-d H:i:s');
        
        $query = $this->db->where('user_id', $user_id)
                          ->where('deleted', 'n')
                          ->update($this->user_tbl, $data);
                          
        return $query;
    }
    
    // ------------------------------------------------------------------------
    
	/**
	 * Update Password
	 *
	 * Hashes the given password and updates the account
	 *
	 */
    public function update_password($password)
    {
        $user = $this->get_user();
        $pass = $this->_hash_string($password, $user['salt']);
        
        $query = $this->db->where('user_id', $user['user_id'])
                          ->where('deleted', 'n')
                          ->update($this->user_tbl, array('password' => $pass));
        
        return $query;
    }
    
    // ------------------------------------------------------------------------
	
	/**
	 * List Roles
	 *
	 */
	public function list_roles()
	{
		$sq = "(SELECT COUNT(u.user_id) FROM {$this->user_tbl} AS u WHERE u.role_id = r.role_id AND u.deleted = 'n') AS user_count";
		
		$query = $this->db->select('r.*, ' . $sq, FALSE)
						  ->where('r.deleted', 'n')
						  ->get($this->role_tbl . ' AS r');
						  
		return $query->num_rows() > 0 ? $query->result_array() : FALSE;
	}
	
	// ------------------------------------------------------------------------
	
	/**
	 * Create Permission
	 *
	 * @param	array
	 * @return 	bool
	 */
	public function create_permission($fields)
	{
		$fields['created'] = date('Y-m-d H:i:s');
		
		$this->db->insert($this->perm_tbl, $fields);
		
		return $this->db->affected_rows() > 0 ? $this->get_permission($this->db->insert_id()) : FALSE;
	}
	
	// ------------------------------------------------------------------------
	
	/**
	 * List Permission
	 *
	 * @param	int				limit
	 * @param	int				offset
	 * @param	string			order_by
	 * @param	string			select params
	 * @param	array			where
	 * @return	array|bool
	 */
	public function list_permissions($limit = '', $offset = '', $order = 'permission_name', $params = '*', $where = '')
	{
		$offset = $offset > 0 ? ($offset - 1) * $limit : 0;
		
		if ($where) $this->db->where($where);
		
		$query = $this->db->select($params)
						  ->where('deleted', 'n')
						  ->order_by($order)
						  ->get($this->perm_tbl, $limit, $offset);
		
		return $query->num_rows() > 0 ? $query->result_array() : FALSE;
	}
	
	// ------------------------------------------------------------------------
	
	/**
	 * Get Permission
	 *
	 */
	public function get_permission($value, $where = 'permission_id')
	{
		$query = $this->db->where($where, $value)
						  ->get($this->perm_tbl, 1);
						  
		return $query->num_rows() > 0 ? $query->row_array() : FALSE;
	}
	
	// ------------------------------------------------------------------------
	
	/**
	 * Get Role Permission
	 *
	 * @return	array
	 */
	public function get_role_permissions($role_id)
	{
		$sub1 = "SELECT GROUP_CONCAT(permission_id) FROM {$this->roleperm_tbl} WHERE role_id = {$role_id}";
		$sub2 = "SELECT GROUP_CONCAT(menu_id) FROM {$this->rolemenu_tbl} WHERE role_id = {$role_id}";
		
		$query = $this->db->select("r.*, ({$sub1}) AS perm_ids, ({$sub2}) AS menu_ids")
						  ->where('r.role_id', $role_id)
						  ->get($this->role_tbl . ' AS r', 1);
						  
		return $query->num_rows() > 0 ? $query->row_array() : FALSE;
	}
	
	// ------------------------------------------------------------------------
	
	/**
	 * Update Permission
	 *
	 */
	public function update_permission($fields, $permission_id)
	{
		$fields['updated'] = date('Y-m-d H:i:s');
		
		$query = $this->db->where('permission_id', $permission_id)
						  ->where('deleted', 'n')
						  ->update($this->perm_tbl, $fields);
						  
		return $query;
	}
	
	// ------------------------------------------------------------------------
	
	/**
	 * Delete Permission
	 *
	 * Deletes permission and child permission if available
	 * and role permissions as well
	 *
	 */
	public function delete_permission($permission_id)
	{
		$perm = $this->get_permission($permission_id);
		
		// delete child permissions
		if ($perm['parent_permission'] == 0)
		{
			$query = $this->db->where('parent_permission', $permission_id)
							  ->where('deleted', 'n')
							  ->update($this->perm_tbl, array('deleted' => 'y'));
		}
		
		$query = $this->db->where('permission_id', $permission_id)
						  ->where('deleted', 'n')
						  ->update($this->perm_tbl, array('deleted' => 'y'));
		
		$this->delete_role_permissions($permission_id, 'permission_id');
		
		return TRUE;
	}
	
	// ------------------------------------------------------------------------
	
	/**
	 * List Role Permissions
	 *
	 */
	public function list_role_permissions()
	{
		$query = $this->db->select()
						  ->join($this->role_tbl . ' AS r', 'r.role_id = rp.role_id', 'left')
						  ->join($this->perm_tbl . ' AS p', 'p.permission_id = rp.permission_id', 'left')
						  ->get($this->roleperm_tbl . ' AS rp');
						  
		return $query->num_rows() > 0 ? $query->result_array() : FALSE;
	}
	
	// ------------------------------------------------------------------------
	
	/**
	 * Get Role
	 *
	 */
	public function get_role($role_id)
	{
		$query = $this->db->where('role_id', $role_id)
						  ->where('deleted', 'n')
						  ->get($this->role_tbl, 1);
						  
		return $query->num_rows() > 0 ? $query->row_array() : FALSE;
	}
	
	// ------------------------------------------------------------------------
	
	/**
	 * Update Role Permissions
	 * 
	 * @params	array	fields
	 * @params	int		role_id
	 */
	public function update_role_permission($fields, $role_id)
	{
		$query = $this->db->where('role_id', $role_id)
						  ->update($this->role_tbl, array('role_name' => $fields['role_name']));
						  
		$this->delete_role_permissions($role_id);
		$this->create_role_permissions($role_id, $fields['permissions']);
		
		return TRUE;
	}
	
	// ------------------------------------------------------------------------
	
	/**
	 * Delete Role Permissions
	 *
	 */
	public function delete_role_permissions($value, $where = 'role_id')
	{
		$query = $this->db->where($where, $value)
						  ->delete($this->roleperm_tbl);
						  
		return TRUE;
	}
	
	// ------------------------------------------------------------------------
	
	/**
	 * Create Role Permissions
	 *
	 */
	public function create_role_permissions($role_id, $fields)
	{
		if (! $fields) return TRUE;
		
		foreach ($fields as $perm)
		{
			$data[] = array(
				'permission_id'	=> $perm,
				'role_id'		=> $role_id
			);
		}
		
		return $this->db->insert_batch($this->roleperm_tbl, $data);
	}
	
	// ------------------------------------------------------------------------
	
	/**
	 * Create Role
	 *
	 */
	public function create_role($fields)
	{
		$this->db->insert($this->role_tbl, $fields);
		
		return $this->db->affected_rows() > 0 ? $this->get_role($this->db->insert_id()) : FALSE;
	}
	
	// ------------------------------------------------------------------------
	
	public function count_permissions()
	{
		$query = $this->db->select('permission_id')
						  ->where('deleted', 'n')
						  ->get($this->perm_tbl);
						  
		return $query->num_rows();
	}
	
	// ------------------------------------------------------------------------
	
}

/* End of file auth_model.php */
/* Location: ./application/models/auth_model.php */